/*
 *Copyright (c) 2024 Black Sesame Technologies
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
*/


////////////////////////////////////////////cmd function////////////////////////////////////////////
//use related path
#include "utility_lite.h"
#include "printf_inc.h" 
#include <string.h> 
#include "RegTest.h" 
#include <stdlib.h>

T_Cmd_list *glb_cmd_list = NULL;
int glb_cmd_cnt = 0;
extern unsigned long __section_test_cnd_table_start;
extern unsigned long __section_test_cnd_table_end;


extern void putc_user(unsigned char c);
unsigned char getc_user(void);

int str2hex(const char *str, unsigned int *value)
{
	unsigned long temp = 0;	
	
	if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')){                      
		str +=2;	
	}
	
	while(*str != '\0')	{
		if ((*str >= '0') && (*str <= '9')){
			temp = temp * 16 + (*str - '0'); 
			str++;
		}
		else if ((*str >= 'a') && (*str <= 'f')){
			temp = temp * 16 + (*str - 'a' + 10); 
			str++;
		}
		else if ((*str >= 'A') && (*str <= 'F')){
			temp = temp * 16 + (*str - 'A' + 10); 
			str++;
		}else{
			putc_user('e');
			putc_user(*str);
			return -1;
		}      
	}
	
	*value= temp;
	 return 0;
}

void delaySoft(int loopcnt){
	while (loopcnt-- > 0){
		asm("nop");	
	}
}

int getHex(unsigned int *value)
{
	char cBuf[35];	
	
	getString(cBuf,35);
	if (str2hex(cBuf,value)){
		hprintf(TSENV, "wrong input\r\n");
		return -1;
	}
	
	return 0;
}

int str2uint(const char *str, unsigned int *value)
{
    unsigned long temp = 0; 
    unsigned long data_type = 0; 

    if (str[0] == '0' && (str[1] == 'x' || str[1] == 'X')){                      
        str +=2;
        data_type = 16; //hex
    }
    else
    {
        data_type = 10; //Dex
    }

    while(*str != '\0') {

        if(data_type == 16)
        {
            if ((*str >= '0') && (*str <= '9')){
                temp = temp * data_type + (*str - '0'); 
                str++;
            }
            else if ((*str >= 'a') && (*str <= 'f')){
                temp = temp * data_type + (*str - 'a' + 10); 
                str++;
            }
            else if ((*str >= 'A') && (*str <= 'F')){
                temp = temp * data_type + (*str - 'A' + 10); 
                str++;
            }else{
                putc_user('e');
                putc_user(*str);
                return -1;
            }  
        }
        else if(data_type == 10)
        {
            if ((*str >= '0') && (*str <= '9')){
                temp = temp * data_type + (*str - '0'); 
                str++;
            }
            else
            {
                putc_user('e');
                putc_user(*str);
                return -1;
            }
        }
    }

    *value= temp;
     return 0;
}

int getUint(unsigned int *value){
    char cBuf[35];  

    getString(cBuf,35);

    if (str2uint(cBuf,value)){
        hprintf(TSENV, "wrong input\r\n");
        return -1;
    }

    return 0;
}

void dumpMem(unsigned int para){		    	
	unsigned int addr, size;

	unsigned int i;
	
	hprintf(TSENV, "\r\ninput addr(hex)\r\n");	
	if (getHex(&addr)){
		return;
	}

	hprintf(TSENV, "\r\ninput dump size(hex)\r\n");	
	if (getHex(&size)){
		size = 4;
	}

	addr &= ~0x3;
	for( i = 0 ;i < size; i += 4){
		if(!(i & 0xf)){
			hprintf(TSENV, "\n\rADDR 0x%08x: ",addr+i);
		}
		hprintf(TSENV, "0x%08x ",REG32_READ(addr+i));
	}
	hprintf(TSENV, "\n");
}

void setMem32(unsigned para){	    
	unsigned int addr;
	unsigned int value;
	
	hprintf(TSENV, "input addr(hex)\r\n");
	if (getHex(&addr)){		
		return;
	}	

	//while(1) {
		hprintf(TSENV, "0x%lx : ? (hex)",addr);
		if (getHex(&value)){	
			return;
		}        
		hprintf(TSENV, "\r\n");        
		REG32_WRITE(addr,value);
    /*    
		addr = addr + 4;
	}
    */
	hprintf(TSENV, "addr 0x%x = 0x%x\r\n",addr,REG32_READ(addr));	
}


void setReg32FromBuf(unsigned int dstReg,unsigned int *buf,unsigned int length){	
	int i = 0;
	
	for (i=0; i<length; i++){
		REG32_WRITE(dstReg+i*4,buf[i]); 
	}	
}



void Intr_interconversion(Intr_ChangeType ChangeType ,unsigned int* int_list , unsigned int int_num)
{
    // csr reg
    unsigned int intlist[70] = {0};
	unsigned int offset = 0;
	unsigned int regnum = 0;
	
    memcpy(intlist , int_list , int_num);
	if (ChangeType >= safety2rt && ChangeType <= safety2Cv)
	{
		regnum = 3;
		switch (ChangeType)
		{
		case safety2rt:
			offset = 0x310;
			break;
		case safety2sw:
			offset = 0x340;
			break;
		case safety2SocA78:
			offset = 0x334;
			break;
		case safety2Db:
			offset = 0x31c;
			break;
		case safety2SocR5:
			offset = 0x328;
			break;
		case safety2Hifi:
			offset = 0x34c;
			break;
		case safety2Cv:
			offset = 0x358;
			break;
		default:
			break;
		}
		REG32_WRITE(0xC0031000+offset, ((intlist[0]) | (intlist[1] << 6) | (intlist[2] << 12) | (intlist[3] << 18) | (intlist[4] << 24) | (intlist[5] << 30)));
		REG32_WRITE(0xC0031000+offset+0x4, (((intlist[5]) >> 2) | (intlist[6] << 4) | (intlist[7] << 10) | (intlist[8] << 16) | (intlist[9] << 22) | (intlist[10] << 28)));
		REG32_WRITE(0xC0031000+offset+0x8, (((intlist[11]) >> 4) | (intlist[12] << 2) | (intlist[13] << 8) | (intlist[14] << 14) | (intlist[15] << 20) | (intlist[16] << 26)));
	}
	else if (ChangeType >= rt2safety && ChangeType <= rt2Cv)
	{
		switch (ChangeType)
		{
		case rt2safety:
			offset = 0x224;
			regnum = 4;
			break;
		case rt2sw:
			offset = 0x214;
			regnum = 4;
			break;
		case rt2Db:
			offset = 0x204;
			regnum = 4;
			break;
		case rt2SocR5:
			offset = 0x234;
			regnum = 4;
			break;
		case rt2Hifi:
			offset = 0x254;
			regnum = 4;
			break;
		case rt2Cv:
			offset = 0x244;
			regnum = 4;
			break;
		default:
			break;
		}
		for (int i=0;i<regnum;i++)
		{
			REG32_WRITE(0xD1036000+offset+0x4*i, ((intlist[4*i]) | (intlist[4*i+1] << 8) | (intlist[4*i+2] << 16) | (intlist[4*i+3] << 24)));
		}
	}
	else if (ChangeType == rt2SocA78)
	{
		offset = 0x168;
		regnum = 8;
		for (int i=0;i<regnum-2;i++)
		{
			REG32_WRITE(0xD1036000+offset+0x4*i, ((intlist[4*i]) | (intlist[4*i+1] << 8) | (intlist[4*i+2] << 16) | (intlist[4*i+3] << 24)));
		}
		offset = 0x264;
		for (int i=6;i<regnum;i++)
		{
			REG32_WRITE(0xD1036000+offset+0x4*(i-6), ((intlist[4*i]) | (intlist[4*i+1] << 8) | (intlist[4*i+2] << 16) | (intlist[4*i+3] << 24)));
		}
	}
	else if (ChangeType >= sw2safety && ChangeType <= sw2Cv)
	{
		switch (ChangeType)
		{
		case sw2safety:
			offset = 0x6c0;
			regnum = 4;
			break;
		case sw2rt:
			offset = 0x680;
			regnum = 8;
			break;
		case sw2SocA78:
			offset = 0x600;
			regnum = 16;
			break;
		case sw2Db:
			offset = 0x640;
			regnum = 4;
			break;
		case sw2SocR5:
			offset = 0x700;
			regnum = 4;
			break;
		case sw2Hifi:
			offset = 0x780;
			regnum = 4;
			break;
		case sw2Cv:
			offset = 0x740;
			regnum = 4;
			break;
		default:
			break;
		}
		for (int i=0;i<regnum;i++)
		{
			REG32_WRITE(0x217B1000+offset+0x4*i, ((intlist[4*i]) | (intlist[4*i+1] << 8) | (intlist[4*i+2] << 16) | (intlist[4*i+3] << 24)));
		}
	}
	else if (ChangeType >= SocA782safety && ChangeType <= SocA782Cv)
	{
		switch (ChangeType)
		{
		case SocA782safety:
			offset = 0x1d4;
			regnum = 6;
			break;
		case SocA782sw:
			offset = 0x1bc;
			regnum = 6;
			break;
		case SocA782rt:
			offset = 0x274;
			regnum = 6;
			break;
		case SocA782Db:
			offset = 0x164;
			regnum = 22;
			break;
		case SocA782SocR5:
			offset = 0x1ec;
			regnum = 22;
			break;
		case SocA782Hifi:
			offset = 0x25c;
			regnum = 6;
			break;
		case SocA782Cv:
			offset = 0x244;
			regnum = 6;
			break;
		default:
			break;
		}
		for (int i=0;i<regnum;i++)
		{
			REG32_WRITE(0x30000000+offset+0x4*i, ((intlist[3*i]) | (intlist[3*i+1] << 10) | (intlist[3*i+2] << 20)));
		}
	}
}

extern T_Cmd_list CmdList[];

void helpCmd(unsigned int para){	
	int i = 0;
	T_Cmd_list *pCmdList = (T_Cmd_list *)glb_cmd_list;	
	
	hprintf(TSENV, "\r\n");

	for( i = 0;i < glb_cmd_cnt;i++){
//	while(pCmdList[i].cmdFn != NULL){
		hprintf(TSENV, pCmdList[i].cmdName);
		hprintf(TSENV, ".........");
		hprintf(TSENV, pCmdList[i].description);
                if (pCmdList[i].attr & CMD_ATTR_AUTO_TEST){
                  putc_user('(');
                  putc_user('a');
                  putc_user(')');
                }
		hprintf(TSENV, "\r\n");		
	}	
}

/*get string(cmd)*/
int getString(char *cmd_buf, int len)
{
	int i = 0;
	unsigned char c;	
	
	while(1)
	{
		if (i > len){
			i = len;
			break;
		}
		
		c = getc_user();
		if((c == 0x0d) || (c == 0x0a))
		{
			cmd_buf[i] = '\0';
			break;
		}
		else if ((c == 0x08) || (c == 0x7f))
		{
			if (i > 0)
				i--;
			
			putc_user(0x08);
			putc_user(0x20);
			putc_user(0x08);
			//putc_user(0x7f);
		}	
		else
		{
			putc_user(c);
			cmd_buf[i++] = c;
		}
	}	
	
	return i;
}

int runCmd(const char * cmdBuf)
{
	const char *pCmd;
	int i = 0;
	T_Cmd_list *pCmdList = (T_Cmd_list *)glb_cmd_list;	
		
	for( i = 0 ; i < glb_cmd_cnt ; i++){
//	while(cmdList[i].cmdFn != NULL){
		pCmd = pCmdList[i].cmdName;
		if (!strcmp(pCmd,cmdBuf)){
			pCmdList[i].cmdFn(pCmdList[i].para);
			return 0;
		}
	}	
	hprintf(TSENV, "%s is wrong command\r\n",cmdBuf);
	
	return i;
}

unsigned char ascii2Byte(char High4bit, char Low4bit)
{
	unsigned char value = 0;

	if ((High4bit >= '0') && (High4bit <= '9')) {
		value = (High4bit - '0')<<4;
	} else if ((High4bit >= 'a') && (High4bit <= 'f')) {
		value = (High4bit - 'a' + 10)<<4;
	} else if ((High4bit >= 'A') && (High4bit <= 'F')) {
		value = (High4bit - 'A' + 10)<<4;
	}

	if ((Low4bit >= '0') && (Low4bit <= '9')) {
		value += (Low4bit - '0');
	} else if ((Low4bit >= 'a') && (Low4bit <= 'f')) {
		value += (Low4bit - 'a' + 10); 			
	} else if ((Low4bit >= 'A') && (Low4bit <= 'F')) {
		value += (Low4bit - 'A' + 10);
	}

	return value;
}

int str2ValStartTail(char *str,unsigned int *val, int valLength8)
{
    unsigned int length;
    unsigned char *pVal;
    char *pStr,asiicLow,asiicHigh;

    length = strlen(str);
    if (length > 2*valLength8) {
        hprintf(DEBUG, "\r\nstring %d too long, error", length);
        return -1;
    }
    pStr = str + length - 1;
    pVal = (unsigned char *)val;
    do {
        asiicLow = *pStr--;

        if (pStr >= str)
            asiicHigh = *pStr--;
        else
            asiicHigh = '0';

        *pVal = ascii2Byte(asiicHigh,asiicLow);
        pVal++;
    }while (pStr >= str);
    return 0;
}

int str2ValStartHead(char *str,unsigned int *val, int valLength8)
{
    unsigned int length;
    unsigned char *pVal;
    char *pStr,asiicLow,asiicHigh;

    length = strlen(str);
    if (length > 2*valLength8) {
        hprintf(DEBUG, "\r\nstring is too long, error");
        return -1;
    }
    if (length%2) {
        hprintf(DEBUG, "\r\nlength is odd, error, must even");
        return -1;
    }
    pStr = str + length - 1;
    pVal = (unsigned char *)val;
    do {
        asiicHigh = *str++;
        asiicLow = *str++;

        *pVal = ascii2Byte(asiicHigh,asiicLow);
        pVal++;
    }while (pStr >= str);
    return 0;
}


/*
4 bit hex to char
*/
char hex2Char(unsigned int val){
	if((val>=0)&&(val<=9))
		return val+0x30;
	else if((val>=10)&&(val<=15))
		return val-10+'A'; 
	
	return 0;
}


int putHex(unsigned int value){
	putc_user('\r');	
	putc_user('\n');	
	
	putc_user(hex2Char((value>>4)&0xf));
	putc_user(hex2Char((value>>0)&0xf));
	putc_user(hex2Char((value>>12)&0xf));
	putc_user(hex2Char((value>>8)&0xf));
	putc_user(hex2Char((value>>20)&0xf));
	putc_user(hex2Char((value>>16)&0xf));
	putc_user(hex2Char((value>>28)&0xf));
	putc_user(hex2Char((value>>24)&0xf));

	return 0;
}


void putStr(unsigned char *ch,unsigned int length){		
    int i=0;

    for (i = 0; i < length; i++) {
        if (i%4 == 0) {
            hprintf(DEBUG, "\r\n");
        }
        putc_user(hex2Char((ch[i]>>4)&0xf));
        putc_user(hex2Char((ch[i]>>0)&0xf));		
    }
}

/*
memset by byte
*/
void memSet8(void *buf, unsigned char val, unsigned int length)
{
	unsigned char *p =(unsigned char *)buf;
	
	int i=0;		
	for (i=0; i<length; i++){
		p[i] = val;
	}
}

/*
memory  compare,return err cnt
*/
int memCmp8(void *buf1, void *buf2, unsigned int length)
{
	int i=0,ret=0;
	unsigned char *p1 = (unsigned char *)buf1;
	unsigned char *p2 = (unsigned char *)buf2;
	
	for (i=0; i<length; i++){
		if(p1[i] != p2[i]){
			ret++;
		}
	}
	
	return ret;
}

/*
memory  copy, care ! not check length ,return dst addr
*/
void *memCpy8(void *dstBuf, void *srcBuf, unsigned int length)
{
	int i=0;
	unsigned char *src = (unsigned char *)srcBuf;
	unsigned char *dst = (unsigned char *)dstBuf;
	
	for (i=0; i<length; i++){
		dst[i] = src[i];
	}
	
	return dstBuf;
}

unsigned int *memCpy32(unsigned int *dest, unsigned int *src, unsigned int count)
{
	//if (NULL == dest || NULL == src || count <= 0)
	//	return NULL;	
	
	while (count--)		
		*(unsigned int *)dest++ = *(unsigned int *)src++;	
	
	return dest;
}
unsigned int String2Decimal(char *string, unsigned char len)
{
    unsigned char i,j;
    unsigned int retValue = 0;
    unsigned int tempU32 = 0;

    if (len < 1) {
        return -1;
    }
    for (i = 0; i < len; i++) {
        if ((string[i] > '9') || (string[i] < '0')) {
            return -1;
        }
        tempU32 = string[i] - '0';
        j = len - i - 1;
        while (j > 0) {
            j--;
            tempU32 *= 10;   
        }
        retValue += tempU32;
    }

    return retValue;
}

int memReadWriteTst(unsigned int ddrMemStartAddr,unsigned int ddrMemEndAddr)
{
	int err = 0;
	unsigned long addr;
	unsigned int delta;
	
	delta=4;
	
	hprintf(DEBUG, "ddrMemStartAddr = 0x%lx, ddrMemEndAddr = 0x%lx\r\n", ddrMemStartAddr, ddrMemEndAddr);

	for (addr = ddrMemStartAddr;addr < (ddrMemEndAddr-3);){

		if (!(addr & (128*1024 - 1))){
			hprintf(DEBUG, "addr = 0x%lx\r\n",addr);
		}
		
		REG32_WRITE(addr,0x12345678);                              
		if (REG32_READ(addr) != 0x12345678){
			err+=1;
			hprintf(DEBUG, "32bit rw err,val = 0x%x\r\n", REG32_READ(addr));	
		}
		
		REG8_WRITE(addr+0,0x12);		
		REG8_WRITE(addr+1,0xAA);		
		REG8_WRITE(addr+2,0x55);		
		REG8_WRITE(addr+3,0xA5);	
		if (REG8_READ(addr+0) != 0x12){
			err+=1;
			hprintf(DEBUG, "8bit rw err0,val = 0x%x\r\n",REG8_READ(addr+0));	
		}		
		if (REG8_READ(addr+1) != 0xAA){
			err+=1;
			hprintf(DEBUG, "8bit rw err1,val = 0x%x\r\n",REG8_READ(addr+1));	
		}		
		if (REG8_READ(addr+2) != 0x55){
			err+=1;
			hprintf(DEBUG, "8bit rw err2,val = 0x%x\r\n",REG8_READ(addr+2));	
		}	
		if (REG8_READ(addr+3) != 0xA5){
			err+=1;
			hprintf(DEBUG, "8bit rw err3,val = 0x%x\r\n",REG8_READ(addr+3));	
		}	
		if (REG32_READ(addr) != 0xA555AA12){
			err+=1;
			hprintf(DEBUG, "8bit rw err4,val =0x%x\r\n",REG32_READ(addr));	
		}		

		REG16_WRITE(addr+2,0xA5A5);		
		if (REG16_READ(addr+2) != 0xA5A5){
			err+=1;
			hprintf(DEBUG, "16bit rw err1, val = 0x%x\r\n", REG16_READ(addr+2));	
		}

		if (REG32_READ(addr) != 0xA5A5AA12){
			err+=1;
			hprintf(DEBUG, "16bit rw err2, val = 0x%x\r\n", REG32_READ(addr));	
		}
		
		addr += delta;		
#if 0
		j <<=1;  
		if (j > (1<<25)){
			j=4;
		}
#endif
	}
	
	hprintf(DEBUG, "err cnt = %d\r\n",err);	
	return err;	
}

/*
 * info = what info would print
 */
void waitInputQ(char *info)
{
   char c;

   if (info != NULL){
      hprintf(TSENV, "=== %s ===\r\n",info);
   }     
   
   hprintf(TSENV, "stop here,press 'q' to quit!!!!\r\n");	
   while (1){
        c = getc_user();
        if (c == 'q'){
            return;
        }
    }
}      




/*
dump value by word(int)
*/
void dumpIntVal(unsigned int *pBuf,unsigned int len32)
{
	unsigned int i;
	
	for (i=0;i < len32;i++){
		if (i%4 == 0){
			hprintf(DEBUG, "\r\n0x%08x->",i*4);
		}
		hprintf(DEBUG, "\t0x%08x",pBuf[i]);
	}
}

/*
buffer bit to lit by word (int)
*/
void Buffer_Big2Lit32(unsigned int *pBuf,unsigned int len32)
{
	unsigned int i;
	
	//putStr(pTmp,tAesObj.msgLen);	
	for (i=0;i < len32;i++){
		pBuf[i] = BigtoLittle32(pBuf[i]);		
	}	
}

int getRegTemp(unsigned int regVal)
{
    double temp;

    temp = -49.002 + 0.32512*regVal - 1.7058*regVal*regVal/10000 + 0.060373*regVal*regVal*regVal/1000000;
    temp -= 0.00092627*regVal*regVal*regVal*regVal/100000000;
    return (int)temp;
}

void system_sleep(void)
{
    while (1) {
        asm("wfi");
    }
}

unsigned int timer_start(unsigned int timer_addr)
{
    //disable timer
    REG32_WRITE(timer_addr+8,0);
    //start config
    REG32_WRITE(timer_addr,0xFFFFFFFE);
    //timer bit2=0,intr unmask
    REG32_WRITE(timer_addr+8,3);

	return REG32(timer_addr+0x4);
}

unsigned int get_timer(unsigned int timer_addr)
{
    return REG32(timer_addr+0x4);
}

void auto_test_cmd(unsigned int para)
{
	int i = 0;
	
	T_Cmd_list *pCmdList = (T_Cmd_list *)glb_cmd_list;	
		
	for( i = 0 ; i < glb_cmd_cnt ; i++){
//	while(cmdList[i].cmdFn != NULL){
		if (pCmdList[i].attr & CMD_ATTR_AUTO_TEST){
	                hprintf(TSENV, "\n\r===Auto test %s====\r\n",pCmdList[i].cmdName);
			pCmdList[i].cmdFn(1);
			hprintf(TSENV, "\n\r===%s....Test Done====\r\n",pCmdList[i].cmdName);
			//return 0;
		}
	}	
	hprintf(TSENV, "Auto test Done.\r\n");
	
	//return i;
}


void cmd_init(void)
{
	int i = 0;
	T_Cmd_list *pCmdList;
	glb_cmd_list = (T_Cmd_list* ) &__section_test_cnd_table_start;
	//glb_cmd_cnt = (unsigned int)((&__section_test_cnd_table_end - &__section_test_cnd_table_start)/sizeof(T_Cmd_list));
	pCmdList =  (T_Cmd_list* )&__section_test_cnd_table_start;
	do{
		i++;
		pCmdList++;
	}while(pCmdList < (T_Cmd_list* )&__section_test_cnd_table_end);
	glb_cmd_cnt = i;
//	printf("[CMD_INIT]Start:%08x , End:%08x size:%08x\n\r",&__section_test_cnd_table_start,&__section_test_cnd_table_end,sizeof(T_Cmd_list));
	return ;
}

extern void prj_logo(void);

static F_postFn fPostCb = NULL;
void cmd_SetPostCb(F_postFn fCb)
{
    fPostCb = fCb;
}


void cmd_main(void)
{
    int len;    
    char cmdBuf[128]={0};
    cmd_init();
    
    //some cmd must run after cmd init
    if (fPostCb != NULL)
        fPostCb();
        
//    printf("[CMD_INIT]cmd_list Satar:%08x ,cmd_cnt:%d.\n\r",glb_cmd_list,glb_cmd_cnt);
//    helpCmd(0);
    while (1){
        prj_logo();
        len=getString(cmdBuf,128);
        putc_user('\r');
        putc_user('\n');
        if (len > 2){
            runCmd((const char*)cmdBuf);
        }
    }    
}

void auto_main(void)
{
    cmd_init();
    
    runCmd("autopre");
    runCmd("autotest");
    runCmd("autolast");  
    while (1) 
       asm("wfi");     
}


CMD_DEFINE(help,helpCmd, 0,"show all cmd",0);
CMD_DEFINE(dump,dumpMem,0,"dump reg or memory",0);
CMD_DEFINE(set32,setMem32,0,"set reg or memory by 32 bit",0);
CMD_DEFINE(autotest,auto_test_cmd,0,"auto test all",0);

